package org.simplextensions.registry.phaselisteners;

import javassist.bytecode.annotation.Annotation;
import org.simplextensions.annotations.ExtensionStyle;
import org.simplextensions.registry.ExtensionPoint;
import org.simplextensions.registry.IExtensionRegistry;
import org.simplextensions.registry.ISimpleXtensionsClassScanner;
import org.simplextensions.registry.SimpleXtensionsBundle;
import org.simplextensions.registry.exceptions.ExtensionsConfigurationException;
import org.simplextensions.scanner.ClassScannerHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExtensionPointClassScanner implements ISimpleXtensionsClassScanner {

	private static final Logger log = LoggerFactory.getLogger(ExtensionPointClassScanner.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.simplextensions.scanner.IScanPhaseListener#scanClass(javassist
	 * .bytecode.ClassFile, javassist.bytecode.annotation.Annotation)
	 */
	public void scanClass(IExtensionRegistry extensionRegistry, SimpleXtensionsBundle bundle, String className, Annotation a) {
		scanAnnotation(extensionRegistry, bundle, a, className);
	}

	public void scanAnnotation(IExtensionRegistry extensionRegistry, SimpleXtensionsBundle bundle, Annotation a, String name) {
		log.trace("scanning extension point's class: " + name);

		String substring = name.substring(name.lastIndexOf(".") + 1);

		String smvId = ClassScannerHelper.getStringValue(a, "id", substring + extensionRegistry.getSequenceValue(substring));
		Class<?>[] cmvEC = ClassScannerHelper.getClassesValue(a, "extensionClass");
		String smvFM = ClassScannerHelper.getStringValue(a, "factoryMethod");
		ExtensionStyle emvStyle = (ExtensionStyle) ClassScannerHelper.getEnumValue(a, "style");

		/*
		 * Class<?> forName = Class.forName(name); if
		 * (!IExtensionPoint.class.isAssignableFrom(forName)) {
		 * log.warn("extension point class: " + name +
		 * " does not implement interface: " +
		 * IExtensionPoint.class.getCanonicalName()); return; }
		 */

		ExtensionPoint extensionPoint = new ExtensionPoint(extensionRegistry, bundle, name, smvId, cmvEC, emvStyle, smvFM);
		extensionRegistry.addExtensionPoint(processExtensionPoint(extensionRegistry, extensionPoint));
	}

	public ExtensionPoint processExtensionPoint(IExtensionRegistry extensionRegistry, ExtensionPoint extensionPoint) {

		for (Class<?> defaultExtensionClass : extensionPoint.getDefaultExtensionClasses())
			if (defaultExtensionClass != null && !defaultExtensionClass.equals(void.class)) {
				for (ExtensionPoint ep : extensionRegistry.getExtensionPointsMD()) {
					if (ep != extensionPoint && ep.getDefaultExtensionClasses() != null
							&& ep.getDefaultExtensionClasses().contains(defaultExtensionClass))
						throw new ExtensionsConfigurationException("multiply extension points:" + extensionPoint.getId() + "," + ep.getId()
								+ " confgured with the same default extension class");
				}
			}
		return extensionPoint;
	}
}